﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace StyleMVVM.ViewModel
{
	/// <summary>
	/// Simple delegating command, based largely on DelegateCommand from PRISM/CAL
	/// </summary>
	/// <typeparam name="T">The type for the </typeparam>
	public class DelegateCommand : ICommand
	{
		private readonly Func<object, bool> canExecuteMethod;
		private readonly Action<object> executeMethod;

		public DelegateCommand(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
		{
			this.executeMethod = executeMethod;
			this.canExecuteMethod = canExecuteMethod;
		}

		public DelegateCommand(Action<object> executeMethod)
		{
			this.executeMethod = executeMethod;
			this.canExecuteMethod = (x) => true;
		}

		public bool CanExecute(object parameter)
		{
			return canExecuteMethod(parameter);
		}

		public void Execute(object parameter)
		{
			executeMethod(parameter);
		}

		/// <summary>
		/// Occurs when changes occur that affect whether the command should execute.
		/// </summary>
		public event EventHandler CanExecuteChanged
		{
			add
			{
				if (canExecuteMethod != null)
				{
					CommandManager.RequerySuggested += value;
				}
			}

			remove
			{
				if (canExecuteMethod != null)
				{
					CommandManager.RequerySuggested -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="CanExecuteChanged" /> event.
		/// </summary>
		[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
			Justification = "The this keyword is used in the Silverlight version")]
		[SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
			Justification = "This cannot be an event")]
		public void RaiseCanExecuteChanged()
		{
			CommandManager.InvalidateRequerySuggested();
		}
	}
}